﻿namespace RPCenter.WindowsAPI
{ 
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Runtime.InteropServices;

    public class NativeNetwork
    {
        public static string GetDnsDomainNameFromNetbiosDomainName(string NetbiosDomain)
        {
            return GetDomainControllerFromDomainName(NetbiosDomain, null, true).DomainName;
        }

        public static string GetDnsDomainNameFromNetbiosDomainName(string NetbiosDomain, string ComputerName)
        {
            return GetDomainControllerFromDomainName(NetbiosDomain, ComputerName, true).DomainName;
        }

        public static DomainControllerInfo GetDomainControllerFromDomainName(string Domain, string ComputerName, bool IsNetbiosDomainName)
        {
            DomainControllerInfo info2;
            IntPtr domainControllerInfo = new IntPtr();
            DomainControllerInfo structure = new DomainControllerInfo();
            ApiDefinitions.DsGetDcNameFlags flags = ApiDefinitions.DsGetDcNameFlags.DS_DIRECTORY_SERVICE_PREFERRED;
            if (IsNetbiosDomainName)
            {
                flags = (flags | ApiDefinitions.DsGetDcNameFlags.DS_IS_FLAT_NAME) | ApiDefinitions.DsGetDcNameFlags.DS_RETURN_DNS_NAME;
            }
            else
            {
                flags = (flags | ApiDefinitions.DsGetDcNameFlags.DS_IS_DNS_NAME) | ApiDefinitions.DsGetDcNameFlags.DS_RETURN_FLAT_NAME;
            }
            try
            {
                IntPtr ptr2= new IntPtr(2121);
                uint num = 0;
                if (!string.IsNullOrEmpty(ComputerName) && (ApiDefinitions.DsGetDcName(ComputerName, Domain, ptr2, null, (int) flags, out domainControllerInfo) == 0L))
                {
                    Marshal.PtrToStructure(domainControllerInfo, structure);
                    return structure;
                }
                num = ApiDefinitions.DsGetDcName(null, Domain, ptr2, null, (int) flags, out domainControllerInfo);
                if (num != 0L)
                {
                    throw new Win32Exception((int) num);
                }
                Marshal.PtrToStructure(domainControllerInfo, structure);
                info2 = structure;
            }
            finally
            {
                if (!(domainControllerInfo == IntPtr.Zero))
                {
                    ApiDefinitions.NetApiBufferFree(domainControllerInfo);
                }
            }
            return info2;
        }

        public static DomainControllerInfo GetDomainControllerFromNetbiosDomainName(string NetbiosDomain)
        {
            return GetDomainControllerFromDomainName(NetbiosDomain, null, true);
        }

        public static DomainControllerInfo GetDomainControllerFromNetbiosDomainName(string NetbiosDomain, string Computer)
        {
            return GetDomainControllerFromDomainName(NetbiosDomain, Computer, true);
        }

        private static List<ApiDefinitions.IP_ADAPTER_INDEX_MAP> GetIPv4Interfaces()
        {
            IntPtr ptr2 = IntPtr.Zero;
            uint dwOutBufLen = 0;
            List<ApiDefinitions.IP_ADAPTER_INDEX_MAP> list = new List<ApiDefinitions.IP_ADAPTER_INDEX_MAP>();
            uint interfaceInfo = 0;
            interfaceInfo = ApiDefinitions.GetInterfaceInfo(ptr2, ref dwOutBufLen);
            if (interfaceInfo != 0x534)
            {
                if (interfaceInfo != 0x7aL)
                {
                    throw new ApplicationException("Received unexpected result from initial call to GetInterfaceInfo API - the last error reported was: " + new Win32Exception().Message);
                }
                IntPtr pIfTable = Marshal.AllocHGlobal((int) dwOutBufLen);
                try
                {
                    if (ApiDefinitions.GetInterfaceInfo(pIfTable, ref dwOutBufLen) != 0L)
                    {
                        throw new ApplicationException("GetInterfaceInfo API failed - the last error reported was: " + new Win32Exception().Message);
                    }
                    int num4 = 0;
                    int num3 = Marshal.ReadInt32(pIfTable, 0);
                    num4 += 4;
                    int num6 = num3 - 1;
                    for (int i = 0; i <= num6; i++)
                    {
                        IntPtr ptr = new IntPtr(pIfTable.ToInt64() + num4);
                        list.Add((ApiDefinitions.IP_ADAPTER_INDEX_MAP) Marshal.PtrToStructure(ptr, typeof(ApiDefinitions.IP_ADAPTER_INDEX_MAP)));
                        num4 += Marshal.SizeOf(typeof(ApiDefinitions.IP_ADAPTER_INDEX_MAP));
                    }
                }
                finally
                {
                    Marshal.FreeHGlobal(pIfTable);
                }
            }
            return list;
        }

        public static string GetNetbiosDomainNameFromDnsDomainname(string DnsDomain)
        {
            return GetDomainControllerFromDomainName(DnsDomain, null, false).DomainName;
        }

        public static string GetNetbiosDomainNameFromDnsDomainname(string DnsDomain, string ComputerName)
        {
            return GetDomainControllerFromDomainName(DnsDomain, ComputerName, false).DomainName;
        }

        public static void JoinToDomain(string DomainName, string DomainUsername, string DomainPassword)
        {
            JoinToDomain(DomainName, DomainUsername, DomainPassword, null);
        }

        public static void JoinToDomain(string DomainName, string DomainUsername, string DomainPassword, string MachineName)
        {
            ApiDefinitions.NET_API_STATUS net_api_status = ApiDefinitions.NetJoinDomain(null, DomainName, null, DomainUsername, DomainPassword, 0x23);
            if (net_api_status == ApiDefinitions.NET_API_STATUS.NERR_ACCT_EXISTS)
            {
                net_api_status = ApiDefinitions.NetJoinDomain(MachineName, DomainName, null, DomainUsername, DomainPassword, 0x21);
            }
            if (net_api_status != ApiDefinitions.NET_API_STATUS.NERR_SUCCESS)
            {
                throw new Win32Exception((int) net_api_status);
            }
        }

        public static void ReleaseIpAddresses()
        {
            List<ApiDefinitions.IP_ADAPTER_INDEX_MAP> list = GetIPv4Interfaces();
            int num3 = list.Count - 1;
            for (int i = 0; i <= num3; i++)
            {
                List<ApiDefinitions.IP_ADAPTER_INDEX_MAP> list2 = list;
                int num4 = i;
                ApiDefinitions.IP_ADAPTER_INDEX_MAP adapterInfo = list2[num4];
                list2[num4] = adapterInfo;
                uint num2 = ApiDefinitions.IpReleaseAddress(ref adapterInfo);
                if (num2 != 0L)
                {
                    throw new Win32Exception((int) num2);
                }
            }
        }

        public static void ReleaseIpAddresses(bool ContinueOnError)
        {
            List<ApiDefinitions.IP_ADAPTER_INDEX_MAP> list = GetIPv4Interfaces();
            int num3 = list.Count - 1;
            for (int i = 0; i <= num3; i++)
            {
                List<ApiDefinitions.IP_ADAPTER_INDEX_MAP> list2 = list;
                int num4 = i;
                ApiDefinitions.IP_ADAPTER_INDEX_MAP adapterInfo = list2[num4];
                list2[num4] = adapterInfo;
                uint num2 = ApiDefinitions.IpReleaseAddress(ref adapterInfo);
                if ((num2 != 0L) && !ContinueOnError)
                {
                    throw new Win32Exception((int) num2);
                }
            }
        }

        public static void RemoveFromDomain(string MachineName, string DomainOrLocalUsername, string DomainOrLocalPassword)
        {
            ApiDefinitions.NET_API_STATUS net_api_status = ApiDefinitions.NetUnjoinDomain(MachineName, DomainOrLocalUsername, DomainOrLocalPassword, 2);
            if (net_api_status != ApiDefinitions.NET_API_STATUS.NERR_SUCCESS)
            {
                throw new Win32Exception((int) net_api_status);
            }
        }

        public static void RenewIpAddresses(bool Release)
        {
            if (Release)
            {
                ReleaseIpAddresses();
            }
            List<ApiDefinitions.IP_ADAPTER_INDEX_MAP> list = GetIPv4Interfaces();
            int num3 = list.Count - 1;
            for (int i = 0; i <= num3; i++)
            {
                List<ApiDefinitions.IP_ADAPTER_INDEX_MAP> list2 = list;
                int num4 = i;
                ApiDefinitions.IP_ADAPTER_INDEX_MAP adapterInfo = list2[num4];
                list2[num4] = adapterInfo;
                uint num2 = ApiDefinitions.IpRenewAddress(ref adapterInfo);
                if (num2 != 0L)
                {
                    throw new Win32Exception((int) num2);
                }
            }
        }

        public static void RenewIpAddresses(bool Release, bool ContinueOnError)
        {
            if (Release)
            {
                ReleaseIpAddresses(ContinueOnError);
            }
            List<ApiDefinitions.IP_ADAPTER_INDEX_MAP> list = GetIPv4Interfaces();
            int num3 = list.Count - 1;
            for (int i = 0; i <= num3; i++)
            {
                List<ApiDefinitions.IP_ADAPTER_INDEX_MAP> list2 = list;
                int num4 = i;
                ApiDefinitions.IP_ADAPTER_INDEX_MAP adapterInfo = list2[num4];
                list2[num4] = adapterInfo;
                uint num2 = ApiDefinitions.IpRenewAddress(ref adapterInfo);
                if ((num2 != 0L) && !ContinueOnError)
                {
                    throw new Win32Exception((int) num2);
                }
            }
        }

        [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
        public sealed class DomainControllerInfo
        {
            public string DomainControllerName;
            public string DomainControllerAddress;
            public int DomainControllerAddressType;
            public Guid DomainGuid;
            public string DomainName;
            public string DnsForestName;
            public int Flags;
            public string DcSiteName;
            public string ClientSiteName;
        }
    }
}

